# The client program to communicate with the server
# 
# MiddleMan allows you to connect to the ActiveBackground::Server
# to push jobs and retrieve jobs. The jobs are managed by
# ActiveBackground::Manager.
module ActiveBackground
  class MiddleMan < Client
    include Enumerable
    include Singleton
    
    def initialize
      @handler = Hash.new
    end
    
    # TODO: Add some checking if the handler has all the expected methods
    def register(handler)
      unless @handler[(handler.class.to_s.split("::")[1]).downcase.to_sym]
        @handler[(handler.class.to_s.split("::")[1]).downcase.to_sym] = handler
      end
    end
    
    # TODO: Need to raise and error if handler doesn't exist
    def method_missing(method, *args)
      return @handler[method.to_sym] if @handler[method.to_sym]
    end
    
    def new_job(name, options={}, *args, &job)
      new_job = Job.new(name, options, args)
      new_job.define_job(&job)
      add_job(new_job.key, new_job)
    end
    
    # 
    # Arguments:
    #   <tt>options</tt>: 
    # 
    # Options:
    #   <tt>:status</tt>: status or array of statusses that need to be count
    #   
    def job_count(options=[])
      prepare
      unless options != []
        @@server.get_jobs().size
      else
        count=0
        @@server.each_job.each do |key, job|
          count+=1 if options[:status].include?(job.status)
        end
        return count
      end
    end

    def job_progress(key)
      prepare
      @@server.send_command_to_job(:progress)
    end
    
    def terminate_job(key)
      prepare
      @@server.send_command_to_job(key, :terminate)
    end
    alias :terminate :terminate_job
    alias :mark_as_terminated :terminate_job
    
    def find(argument, options={}, *args)
      prepare
      case argument
        when :all
          if block_given?
            get_jobs {|jobs| yield jobs}
          else
            get_jobs
          end
        when :first
          get_jobs().each {|key, job| return job}
        when :last
          get_jobs().each {|key, job| last=job}; return last;
        else
          @@server.find(argument)
      end
    end
        
    def server_terminate
      prepare
      @@server.terminate
    end
    
    def server_wait
      @@server.wait if @@server
    end    
    
    # returns all -active- jobs as a hash (containing sub hashes)
    def get_jobs()
      prepare
      if block_given?
        @@server.get_jobs() {|jobs| yield jobs}
      else
        return @@server.get_jobs()
      end
    end
    alias :jobs :get_jobs
    alias :[] :get_jobs
    
    # FIXME: need to get this to work
    def each_job
      @@server.get_jobs().each do |jobs|
        jobs.each do |key, job|
          yield key, job
        end
      end
    end
        
    # get a job maching the passed key
    def get_job(key)
      prepare
      @@server.get_job(key)
    end
    alias :job :get_job
    alias :[] :get_job
    
    # add job with a uniq key
    def add_job(key, job)
      prepare
      @@server.add_job(key, job)
    end
    alias :add :add_job
    alias :[] :add_job
      
    # remove job matching the supplied key
    def remove_job(key)
      prepare
      @@server.remove_job(key)
    end
    alias :remove :remove_job
    alias :delete :remove_job
    alias :kill :remove_job
    alias :delete! :remove_job
  end
end